package com.personal.dataconvert;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.personal.core.bean.CountEntity;
import com.personal.core.data.DataColumn;
import com.personal.core.data.DataRow;
import com.personal.core.data.DataTable;
import com.personal.core.utils.CoreUtil;
import com.personal.core.utils.JsonUtil;
import com.personal.core.utils.StringUtil;
import com.personal.dataconvert.bean.HeaderConfig;
import com.personal.dataconvert.bean.HtmlConfig;
import com.personal.dataconvert.port.Data2DataGrid;
import com.personal.dataconvert.port.Data2Html;
import com.personal.dataconvert.util.ExcelHtmlUtil;

/**
 * EasyUI中 DataTable 转DataGrid
 * @author cuibo
 */
public class DataTable2DataGrid_EUI implements Data2DataGrid
{
    
    
    /** 报表数据 */
    private DataTable table;

    /** splitFlag 表头分割标记。默认是点 */
    private String splitFlag = ".";
    
    /** 2017 06 02 新增手动注入HtmlConfig */
    private HtmlConfig htmlConfig;
    

    private DataTable2DataGrid_EUI()
    {
    }

    private DataTable2DataGrid_EUI(Builder builder)
    {
        this.table = builder.table;
        this.splitFlag = builder.splitFlag;
        this.htmlConfig = builder.htmlConfig;
        createHtmlConfig();
    }
    
    /**
     * 构建HtmlConfig
     * @return
     * @throws Exception
     */
    private void createHtmlConfig()
    {
        if (htmlConfig != null)
        {
            return;
        }
        htmlConfig = new HtmlConfig();
        htmlConfig.setName(table.getTableName());
        List<HeaderConfig> headerConfigs = null;
        try
        {
            headerConfigs = ExcelHtmlUtil.createTrees(table, splitFlag);
        } catch (Exception e)
        {
        }
        if (CoreUtil.isEmpty(headerConfigs))
        {
            throw new IllegalArgumentException("datatable信息不合法，创建表头配置失败！");
        }
        htmlConfig.setTableClass(CoreUtil.parseStr(table.getTag()));
        htmlConfig.setHeaderConfigs(headerConfigs);
    }
    
    @Override
    public String createColums() throws Exception
    {
        if (CoreUtil.isEmpty(htmlConfig.getHeaderConfigs()))
        {
            return "[]";
        }
        List<? extends HeaderConfig> trees = htmlConfig.getHeaderConfigs();
        // 表头行数即森林中所有节点中最大的深度
        if (trees == null || trees.isEmpty())
        {
            return "[]";
        }
        int maxRow = ExcelHtmlUtil.getMaxDeepFromTrees(trees);
        List<HeaderConfig> rowHeaderConfigs = null;
        for (int i = 0; i < maxRow; i++)
        {
            // 逐层构建行
            rowHeaderConfigs = ExcelHtmlUtil.getHeaderConfigsByDeepLength(i + 1, trees);
            if (CoreUtil.isEmpty(rowHeaderConfigs))
            {
                continue;
            }
            for (HeaderConfig headerConfig : rowHeaderConfigs)
            {
                if (!headerConfig.isDisplay())
                {
                    continue;
                }
                // 跨行数。如果当前节点距离子节点中的最大深度差大于等于其相邻的最大深度差,并且其深度差大于0 ，则不跨行
                int rowspan = ExcelHtmlUtil.getMaxDeepLength(rowHeaderConfigs, headerConfig);
                int deepLength = headerConfig.getMaxDeepLength();
                // 如果headerConfig仍有子集合，则随机生成一个列名，不然列宽会冲突
                if (!headerConfig.isLeaf())
                {
                    headerConfig.setValue(CoreUtil.newShortUuId());
                }
                if (deepLength < rowspan && deepLength == 0)
                {
                    headerConfig.setRowspan(rowspan - deepLength + 1);
                    headerConfig.setColspan(headerConfig.getMaxWidth(new CountEntity()));
                } else
                {
                    headerConfig.setRowspan(1);
                    headerConfig.setColspan(headerConfig.getMaxWidth(new CountEntity()));
                }
            }
        }
        List<List<Map<String, Object>>> list = new ArrayList<List<Map<String,Object>>>();
        for (int i = 0; i < maxRow; i++)
        {
            // 逐层构建行
            rowHeaderConfigs = ExcelHtmlUtil.getHeaderConfigsByDeepLength(i + 1, trees);
            if (CoreUtil.isEmpty(rowHeaderConfigs))
            {
                continue;
            }
            List<Map<String, Object>> child = new ArrayList<Map<String,Object>>();
            for (HeaderConfig headerConfig : rowHeaderConfigs)
            {
                if (!headerConfig.isDisplay())
                {
                    continue;
                }
                child.add(headerConfig2Map(headerConfig));
            }
            list.add(child);
        }
        return JsonUtil.toJson(list);
    }

    
//    @Override
//    public String createColums() throws Exception
//    {
//        if (CoreUtil.isEmpty(htmlConfig.getHeaderConfigs()))
//        {
//            return "[]";
//        }
//        List<? extends HeaderConfig> trees = htmlConfig.getHeaderConfigs();
//        // 表头行数即森林中所有节点中最大的深度
//        if (trees == null || trees.isEmpty())
//        {
//            return null;
//        }
//        int maxRow = ExcelHtmlUtil.getMaxDeepFromTrees(trees);
//        StringBuilder result = new StringBuilder();
//        result.append("[");
//        List<HeaderConfig> rowHeaderConfigs = null;
//        int rowspan = 1;
//        int deepLength = 1;
//        for (int i = 0; i < maxRow; i++)
//        {
//            result.append("[");
//            // 逐层构建行
//            rowHeaderConfigs = ExcelHtmlUtil.getHeaderConfigsByDeepLength(i + 1, trees);
//            if (rowHeaderConfigs.size() > 0)
//            {
//                for (HeaderConfig headerConfig : rowHeaderConfigs)
//                {
//                    if (!headerConfig.isDisplay())
//                    {
//                        continue;
//                    }
//                    // 跨行数。如果当前节点距离子节点中的最大深度差大于等于其相邻的最大深度差,并且其深度差大于0 ，则不跨行
//                    rowspan = ExcelHtmlUtil.getMaxDeepLength(rowHeaderConfigs, headerConfig);
//                    deepLength = headerConfig.getMaxDeepLength();
//                    result.append("{");
//                    // 如果headerConfig仍有子集合，则随机生成一个列名，不然列宽会冲突
//                    if (headerConfig.isLeaf())
//                    {
//                        result.append(" \"field\":\"").append(headerConfig.getValue()).append("\",");
//                    } else
//                    {
//                        result.append(" \"field\":\"").append(CoreUtil.newShortUuId()).append("\",");
//                    }
//                    result.append(" \"title\":\"").append(headerConfig.getDisplayName()).append("\",");
//                    if (headerConfig.getWidth() > 0)
//                    {
//                        result.append(" \"width\":").append(headerConfig.getWidth()).append(",");
//                    }
//                    result.append(" \"align\":\"").append(CoreUtil.isEmpty(headerConfig.getStyle()) ? HeaderConfig.CENTER : headerConfig.getStyle()).append("\",");
//                    if (deepLength < rowspan && deepLength == 0)
//                    {
//                        result.append(" \"rowspan\":").append(rowspan - deepLength + 1).append(",")
//                        .append(" \"colspan\":").append(headerConfig.getMaxWidth(new CountEntity())).append("");
//                    } else
//                    {
//                        result.append(" \"rowspan\":").append(1).append(",")
//                        .append(" \"colspan\":").append(headerConfig.getMaxWidth(new CountEntity())).append("");
//                    }
//                    result.append(" },\n");
//                }
//            }
//            result.deleteCharAt(result.length() - 2);
//            result.append("],");
//        }
//        result.deleteCharAt(result.length() - 1);
//        result.append("]");
//        return result.toString();
//    }
    
    private Map<String, Object> headerConfig2Map(HeaderConfig config)
    {
        Map<String, Object> result = new LinkedHashMap<String, Object>();
        result.put("field", config.getValue());
        result.put("title", config.getDisplayName());
        if (config.getWidth() > 0)
        {
            result.put("width", config.getWidth());
        }
        result.put("align", CoreUtil.isEmpty(config.getAlign()) ? HeaderConfig.CENTER : config.getAlign());
        result.put("rowspan", config.getRowspan());
        result.put("colspan", config.getColspan());
        return result;
    }
    
    @Override
    public String createRows() throws Exception
    {
        if (!CoreUtil.checkDataTableHasData(table))
        {
            return "[]";
        }
        List<Map<String, Object>> list = new ArrayList<Map<String,Object>>();
        for (DataRow row : table.getRows())
        {
            list.add(dataRow2Map(table, row));
        }
        return JsonUtil.toJson(list);  
    }

//    @Override
//    public String createRows() throws Exception
//    {
//        if (!CoreUtil.checkDataTableHasData(table))
//        {
//            return "[]";
//        }
//        StringBuilder result = new StringBuilder();
//        result.append("[");
//        int rowIndex = -1;
//        for (DataRow row : table.getRows())
//        {
//            rowIndex ++;
//            result.append(dataRow2Json(row));
//            if (rowIndex != table.getRows().size() - 1)
//            {
//                result.append(",");
//            }
//        }
//        result.append("]");
//        return result.toString();
//    }
    
    @SuppressWarnings("unused")
    private String dataRow2Json(DataRow row)
    {
        StringBuilder result = new StringBuilder();
        dataRow2JsonImpl(result, row);
        return result.toString();
    }
    
    private Map<String, Object> dataRow2Map(DataTable table, DataRow row)
    {
        Map<String, Object> result = new LinkedHashMap<String, Object>();
        String rowStyle = CoreUtil.parseStr(row.getItemMap().get(Data2Html.TRSTYLE));
        int colIndex = -1;
        for (DataColumn column : table.getColumns())
        {
            colIndex ++;
            String value = CoreUtil.parseStr(row.getItemMap().get(column.getColumnName()));
            // 2017 03 13 新增事件支持
            String tdClick = CoreUtil.parseStr(row.getItemMap().get(column.getColumnName() + Data2Html.TDCLICK));
            if (!CoreUtil.isEmpty(tdClick))
            {
                StringBuilder b = new StringBuilder();
                b.append("<a class='tdlink' href='javascript:void(0)'").append(" onclick='").append(tdClick).append("' ");
                if (row.getItemMap().get(column.getColumnName() + Data2Html.TDDATAMAP) != null)
                {
                    Map<?, ?> map =  (Map<?, ?>) row.getItemMap().get(column.getColumnName() + Data2Html.TDDATAMAP);
                    if (!CoreUtil.isEmpty(map))
                    {
                        for (Entry<?, ?> entry : map.entrySet())
                        {
                            b.append(entry.getKey()).append("  = '").append(CoreUtil.parseStr(entry.getValue())).append("' ");
                        }
                    }
                }
                // 如果有rowStyle并且是第一列，则在第一列添加这个标记
                if (colIndex == 0 && !CoreUtil.isEmpty(rowStyle))
                {
                    b.append(" style='").append(rowStyle).append("'");
                }
                b.append(" >").append(value).append("</a>");
                result.put(column.getColumnName(), b.toString());
            } else
            {
                // 如果有rowStyle并且是第一列，则在第一列添加这个标记
                if (colIndex == 0 && !CoreUtil.isEmpty(rowStyle))
                {
                    StringBuilder b = new StringBuilder();
                    b.append("<span ").append("style='").append(rowStyle).append("' >").append(value).append("</span>\"");
                    result.put(column.getColumnName(), b.toString());
                } else
                {
                    result.put(column.getColumnName(), value);
                }
            }
        }
        return result;
    }
    
    private void dataRow2JsonImpl(StringBuilder result, DataRow row)
    {
        result.append("{ ");
        int colIndex = -1;
        String rowStyle = CoreUtil.parseStr(row.getItemMap().get(Data2Html.TRSTYLE));
        for (DataColumn column : table.getColumns())
        {
        	String value = CoreUtil.parseStr(row.getItemMap().get(column.getColumnName()));
        	value = StringUtil.replace(value, "\"", "\\\"");
            colIndex ++;
            // 2017 03 13 新增事件支持
            String tdClick = CoreUtil.parseStr(row.getItemMap().get(column.getColumnName() + Data2Html.TDCLICK));
            if (!CoreUtil.isEmpty(tdClick))
            {
                result.append("\"").append(column.getColumnName()).append("\":\"")
                    .append("<a class='tdlink' href='javascript:void(0)'").append(" onclick='").append(tdClick).append("' ");
                if (row.getItemMap().get(column.getColumnName() + Data2Html.TDDATAMAP) != null)
                {
                    Map<?, ?> map =  (Map<?, ?>) row.getItemMap().get(column.getColumnName() + Data2Html.TDDATAMAP);
                    if (!CoreUtil.isEmpty(map))
                    {
                        for (Entry<?, ?> entry : map.entrySet())
                        {
                            result.append(entry.getKey()).append("  = '").append(CoreUtil.parseStr(entry.getValue())).append("' ");
                        }
                    }
                }
                // 如果有rowStyle并且是第一列，则在第一列添加这个标记
                if (colIndex == 0 && !CoreUtil.isEmpty(rowStyle))
                {
                    result.append(" style='").append(rowStyle).append("'");
                }
                result.append(" >").append(value).append("</a>").append("\"");
            } else
            {
                // 如果有rowStyle并且是第一列，则在第一列添加这个标记
                if (colIndex == 0 && !CoreUtil.isEmpty(rowStyle))
                {
                    result.append("\"").append(column.getColumnName()).append("\":\"<span ").append("style='").append(rowStyle).append("' >").append(value).append("</span>\"");
                } else
                {
                    result.append("\"").append(column.getColumnName()).append("\":\"").append(value).append("\"");
                }
            }
            if (colIndex != table.getColumns().size() - 1)
            {
                result.append(",");
            }
        }
        result.append("}");
    }
    

    /**
     * 建造
     * @author cuibo
     */
    public static class Builder
    {
        private DataTable table;
        private String splitFlag = ".";
        private HtmlConfig htmlConfig;

        public Builder setDataTable(DataTable table)
        {
            this.table = table;
            return this;
        }

        public Builder setSplitFlag(String splitFlag)
        {
            this.splitFlag = splitFlag;
            return this;
        }

        public Builder setHtmlConfig(HtmlConfig htmlConfig)
        {
            this.htmlConfig = htmlConfig;
            return this;
        }
        
        public DataTable2DataGrid_EUI build()
        {
            return new DataTable2DataGrid_EUI(this);
        }
    }


}
